package com.yum.framework.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.NoOpPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.authentication.AuthenticationFailureHandler;
import org.springframework.security.web.authentication.AuthenticationSuccessHandler;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import org.springframework.security.web.authentication.logout.LogoutSuccessHandler;
import org.springframework.security.web.csrf.CsrfFilter;
import org.springframework.web.filter.CharacterEncodingFilter;

import javax.annotation.Resource;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;

/**
 * Package: com.yum.framework.config
 * Description： TODO
 * Author: Forest
 * Date: Created in 2021/3/28 13:01
 * Version: 0.0.1
 * Modified By: duforest
 */
@EnableWebSecurity
@Configuration
@EnableGlobalMethodSecurity(prePostEnabled = true)//开启方法安全级别的控制
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {

    /**
     * 需要放行的URL
     */
    private static final String[] AUTH_WHITELIST = {
            "/sys/user/**",
            "/swagger-resources",
            "/swagger-resources/**",
    };


    @Resource
    private UserDetailsService userDetailsService;

    /**
     * 设置加密方式
     */
    @Bean
    PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
        // 采用不加密的方式
//        return NoOpPasswordEncoder.getInstance();
    }


    /**
     * 用户认证
     */
    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(userDetailsService);
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.formLogin()
                .loginProcessingUrl("/doLogin")// 自定义页面的登录路径，注意要与登录页面的action值一致，<form action="/doLogin" method="post">
                .successHandler(new AuthenticationSuccessHandler() {//实现登录成功后向前端发送json格式的回馈信息
                    @Override
                    public void onAuthenticationSuccess(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Authentication authentication) throws IOException, ServletException {
                        Map<String, Object> map = new HashMap<>();
                        map.put("msg", "登录成功！");
                        map.put("principal", authentication.getPrincipal());
                        httpServletResponse.sendRedirect("swagger-ui.html");

                    }
                })
                // 登录失败Url
                .failureHandler(new AuthenticationFailureHandler() {
                    @Override
                    public void onAuthenticationFailure(HttpServletRequest req, HttpServletResponse resp, AuthenticationException e) throws IOException, ServletException {
                        Map<String, Object> map = new HashMap<>();
                        map.put("msg", "登录失败！");
                        resp.setContentType("application/json:charset=utf-8");
                        resp.sendRedirect("login.html");
                    }
                })
                .and()
                .authorizeRequests() // 定义哪些URL需要被保护、哪些不需要被保护
                .antMatchers(AUTH_WHITELIST).permitAll()// 设置所有人都可以访问登录页面
                .antMatchers("/swagger-ui.html").hasAuthority("admin")// 设置admin可以访问登录页面
                .anyRequest().authenticated();
        http.csrf().disable();// 禁用跨站攻击
        //解决中文乱码问题
        CharacterEncodingFilter filter = new CharacterEncodingFilter();
        filter.setEncoding("UTF-8");
        filter.setForceEncoding(true);
        http.addFilterBefore(filter, CsrfFilter.class);

    }

}
